package org.example.test1;

import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
import java.util.HashMap;
import java.util.Map;

public class MonthGroup extends Group implements RangeGenerable {
    /**
     * 1.类继承extends，一个类可以获得父类所有非私有属性和方法
     * 2.类可以implement接口，定义了类必须实现的行为，但不提供具体实现
     * 3.一个类可以继承另一个类。还可以实现多个接口
     */

    /**
     * 总结
     * 继承通过 extends 关键字，用于获得父类的功能。
     * 接口实现通过 implements 关键字，用于获得行为特性（可以是多个接口 多个接口用，隔开）。
     * 通过继承类并实现接口，一个类既可以继承父类的特性，也可以定义多个接口中的行为
     */
    public MonthGroup() {//构造函数
    }

    public MonthGroup(LocalDate date) {
        super(date);//用于初始化MonthGroup对象的日期 super(date)调用的是当前类（YearGroup）的父类的构造器
    }

    /**
     * super用于调用父类构造器或父类方法
     * @return
     */
    @Override
    public String getDisplayName() {//格式化为 "年-月" 的形式
        return String.format(Unit.MONTH.getFormatter(), date.getYear(), date.getMonth().getValue());
    }

    @Override
    public int compareTo(LocalDate o) {
        return o.getYear() == date.getYear() && o.getMonth().equals(date.getMonth()) ? 0 : -1;
    }//0表示在同年同月

    @Override
    public Map<Group, Counter> generate(LocalDate start, LocalDate end) {
        /**
         * 匿名内部类基本写法
         *         创建匿名内部类：在 new 后直接写出需要继承的类或接口类型，后跟大括号 {} 来定义匿名内部类的具体实现。
         *         一次性使用：匿名内部类通常在定义时创建，并马上使用，不会重用。
         *         省略类名：由于匿名内部类没有类名，构造函数也必须省略。可以在大括号内直接初始化变量和方法。
         */
//       //匿名内部类
//        return new HashMap<Group,Counter>() {{
//            LocalDate current = start.with(TemporalAdjusters.firstDayOfMonth());//将日期调整为当月的第一天。
//            while (!current.isAfter(end)) {
//                put(new MonthGroup(current), new Counter(0, 0));
//                //将一个新的 MonthGroup 对象和一个新的 Counter 对象放入 Map 中。
//                current = current.plusMonths(1).with(TemporalAdjusters.firstDayOfMonth());
//                //将 current 日期增加一个月，并调整为下个月的第一天。
//            }
//        }};
        /**
         *  代码详解
         *         new HashMap<Group, Counter>() {{ ... }}：
         *
         *         第一对大括号 {} 表示创建了一个 HashMap 的匿名子类。
         *         第二对大括号 {} 是实例初始化块，允许我们直接对 HashMap 进行初始化。
         *         实例初始化块：
         *
         *         在第二个 {} 中，我们可以写代码来初始化 HashMap，如向 Map 中添加 MonthGroup 和 Counter 的键值对。
         *         每次循环都将一个新的 MonthGroup（代表特定月份）和一个计数器 Counter 对象放入 Map 中。
         */


        //写全的写法
        Map<Group, Counter> result = new HashMap<>();//标准模式创建HashMap
        LocalDate current = start.with(TemporalAdjusters.firstDayOfMonth());//将start调整为该月的第一天
//        .with()是java中Temporal接口提供的方法，用于日期和时间调整。 然后返回cuurent是一个新日期的对象
//        with(...) 的用途是基于当前日期生成新的日期对象，使得代码更加灵活，同时确保原始日期值不变
//        常见用法示例
//        调整为某月的第一天：start.with(TemporalAdjusters.firstDayOfMonth())
//        调整为某月的最后一天：start.with(TemporalAdjusters.lastDayOfMonth())
//        调整为一年的第一天：start.with(TemporalAdjusters.firstDayOfYear())
//        调整为下一个指定的工作日：start.with(TemporalAdjusters.next(DayOfWeek.MONDAY))
        // 循环遍历直到 current 超过 end
        while (!current.isAfter(end)) {
            // 创建一个新的 MonthGroup 和 Counter，并放入结果 map 中
            result.put(new MonthGroup(current), new Counter(0, 0));
//            new Counter(0, 0) 为每个 MonthGroup 创建了一个新的、独立的计数对象，使得在后续统计中能够针对每个时间分组单独记录数据。
            // 将 current 日期加一个月，并重置为该月的第一天
            current = current.plusMonths(1).with(TemporalAdjusters.firstDayOfMonth());
//            每次循环后，将 current 日期移动到下一个月的第一天。这样，current 总是指向当前处理月份的第一天，方便用作按月进行分组或计数的基准日期。
        }
        return result;
    }
    @Override
    public LocalDate getDate() {
        return date;
    }//return date 用于返回成员变量的值
}
